﻿using CsvHelper.Configuration;
using log4net;
using Lottery.Classes;
using Lottery.Error;
using Lottery.Model;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Lottery.Data
{
    class WinnerData
    {

        private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        private static WinnerData instances = null;

        public static WinnerData Instances
        {
            get
            {
                if (instances == null)
                    instances = new WinnerData();
                return WinnerData.instances;
            }
        }

        internal List<WinnerInfo> WinnerInfos { get => winnerInfos; set => winnerInfos = value; }

        private TxtData<WinnerInfo> txtData;

        /// <summary>
        /// 中奖列表
        /// </summary>
        private List<WinnerInfo> winnerInfos = new List<WinnerInfo>();

        private WinnerData()
        {
            if (winnerInfos == null || winnerInfos.Count <= 0)
            {
                winnerInfos = this.loadWinners(MyResources.GetConfigPath(MyResources.WinnersName));
            }
        }

        public List<WinnerInfo> loadWinners(string fileName)
        {
            txtData = new TxtData<WinnerInfo>(fileName);
            txtData.ClassMap = typeof(WinnerInfoMap);
            List<WinnerInfo> winnerInfos = txtData.readToObject();
            return winnerInfos;
        }

        public int existGiftLevel(GroupRule groupRule)
        {

            var reults = this.winnerInfos.Where(winner => matchGiftLevel(groupRule,winner));
            return reults.ToList().Count;
        }

        public bool matchGiftLevel(GroupRule groupRule, WinnerInfo winner)
        {
            if (string.IsNullOrEmpty(groupRule.GiftLevelName))
            {
                return false;
            }
            else
            {
                if (groupRule.GiftLevelName.Trim().ToUpper().Equals(winner.GiftLevelName.Trim().ToUpper()))
                {
                    return groupRule.match(winner.StaffCompany, winner.StaffDept);
                }
            }
            return false;
        }


        /// <summary>
        /// 存在多少已抽取商品数量
        /// </summary>
        /// <returns></returns>
        public int existGift(String giftName)
        {
            int result = 0;
            foreach (WinnerInfo winnerInfo in this.winnerInfos)
            {
                if (winnerInfo.GiftName.Trim().ToUpper().Equals(giftName.Trim().ToUpper()))
                {
                    result++;
                }
            }
            return result;

        }

        public int existStaff(String jobNo)
        {
            int result = 0;
            foreach (WinnerInfo winnerInfo in this.winnerInfos)
            {
                if (winnerInfo.JobNo.Trim().ToUpper().Equals(jobNo.Trim().ToUpper()))
                {
                    result++;
                }
            }
            return result;

        }


        public List<WinnerInfo> GoToWins(StaffInfo staff, GiftInfo gift)
        {
            List<WinnerInfo> winnerInfos = new List<WinnerInfo>();
            try
            {

                StaffInfo staffWinner = null;
                for (int i = 0; i < gift.Batch; i++)
                {
                    if (staffWinner == null)
                    {
                        staffWinner = staff;
                        log.InfoFormat("传入的中奖员工:{0},{1}", staffWinner.JobNo, staffWinner.Name);
                    }
                    else
                    {
                        staffWinner = StaffData.Instances.RandomStaff(gift);
                        log.InfoFormat("随机出中奖人是:{0},{1}", staffWinner.JobNo, staffWinner.Name);
                    }
                    lock (staffWinner)
                    {

                        WinnerInfo winner = this.GoToWin(staffWinner, gift);
                        if (winner == null)
                            continue;
                        winnerInfos.Add(winner);
                      
                    }
                }
            }
            catch (GiftNoNumberError e)
            {
                log.Error(e);
            }
            catch (Exception e)
            {
                log.Error(e);
                throw e;
            }
            finally
            {
                this.write();
            }
            return winnerInfos;
        }

        /// <summary>
        /// 中奖了
        /// </summary>
        /// <param name="gift">中奖商品</param>
        /// <param name="staff">中奖人</param>
        private WinnerInfo GoToWin(StaffInfo staff, GiftInfo gift)
        {
            if (gift ==null|| gift.OddNumber <= 0)
            {
                log.InfoFormat("奖品已经被抽完不产生中奖者");
                throw new GiftNoNumberError();
            }
            lock (this.winnerInfos)
            {
                log.InfoFormat("目前中奖人是:{0},{1}", staff.JobNo, staff.Name);
                //生成新的中奖人
                WinnerInfo winner = new WinnerInfo();
                winner.StaffCompany = staff.Company;
                winner.StaffName = staff.Name;
                winner.StaffDept = staff.Dept;
                winner.JobNo = staff.JobNo;
                winner.GiftLevel = gift.Level;
                winner.GiftLevelName = gift.LevelName;
                winner.GiftName = gift.Name;
                winner.GiftUnit = gift.Unit;
                winner.WinTime = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", System.Globalization.DateTimeFormatInfo.InvariantInfo);
                //添加到中奖名单中
                this.winnerInfos.Add(winner);
                //去掉商品
                GiftData.Instances.removeGiftNum(gift);
                //去掉中奖者
                StaffData.Instances.removeWinner(staff);

                return winner;
            }
        }

        public void clean()
        {
            this.winnerInfos.Clear();
            txtData.write(this.winnerInfos);
            GiftData.Instances.reload();
            StaffData.Instances.reload();
        }


        /// <summary>
        /// 追加中奖人
        /// </summary>
        /// <param name="winner"></param>
        public void write()
        { 
            //this.winnerInfos.Add(winner);
            txtData.write(this.winnerInfos);
        
        }


        public class WinnerInfoMap : ClassMap<WinnerInfo>
        {
            public WinnerInfoMap()
            {
                Map(m => m.JobNo).Name("工号");
                Map(m => m.StaffName).Name("姓名");
                Map(m => m.StaffDept).Name("部门");
                Map(m => m.StaffCompany).Name("公司");
                Map(m => m.GiftLevelName).Name("奖品等级");
                Map(m => m.GiftName).Name("奖品名称");
                Map(m => m.GiftNum).Name("奖品个数");
                Map(m => m.GiftUnit).Name("奖品单位");
                Map(m => m.WinTime).Name("中奖时间");

            }
        }

    }
}
